1   /*
2    * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   */
23  
24  /*
25   * @test
26   * @bug 6850113
27   * @summary confirm the behavior of new Bidi implementation. (Backward compatibility)
28   */
29  
30  import java.awt.font.NumericShaper;
31  import java.awt.font.TextAttribute;
32  import java.text.AttributedString;
33  import java.text.Bidi;
34  import java.util.Arrays;
35  
36  public class BidiConformance {
37  
38      /* internal flags */
39      private static boolean error = false;
40      private static boolean verbose = false;
41      private static boolean abort = false;
42  
43      public static void main(String[] args) {
44          for (int i = 0; i < args.length; i++) {
45              String arg = args[i];
46              if (arg.equals("-verbose")) {
47                  verbose = true;
48              } else if (arg.equals("-abort")) {
49                  abort = true;
50              }
51          }
52  
53          BidiConformance bc = new BidiConformance();
54          bc.test();
55  
56          if (error) {
57              throw new RuntimeException("Failed.");
58          } else {
59              System.out.println("Passed.");
60          }
61      }
62  
63      private void test() {
64          testConstants();
65          testConstructors();
66          testMethods();
67  
68          testMethods4Constructor1();  // Bidi(AttributedCharacterIterator)
69          testMethods4Constructor2();  // Bidi(String, int)
70          testMethods4Constructor3();  // Bidi(char[], ...)
71      }
72  
73      private void testConstants() {
74          System.out.println("*** Test constants");
75  
76          checkResult("Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT",
77                       -2, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
78          checkResult("Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT",
79                       -1, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
80          checkResult("Bidi.DIRECTION_LEFT_TO_RIGHT",
81                       0, Bidi.DIRECTION_LEFT_TO_RIGHT);
82          checkResult("Bidi.DIRECTION_RIGHT_TO_LEFT",
83                       1, Bidi.DIRECTION_RIGHT_TO_LEFT);
84      }
85  
86      private void testConstructors() {
87          System.out.println("*** Test constructors");
88  
89          testConstructor1();  // Bidi(AttributedCharacterIterator)
90          testConstructor2();  // Bidi(String, int)
91          testConstructor3();  // Bidi(char[], ...)
92      }
93  
94      private void testMethods() {
95          System.out.println("*** Test methods");
96  
97          testMethod_createLineBidi1();
98          testMethod_createLineBidi2();
99          testMethod_getLevelAt();
100         testMethod_getRunLevel();
101         testMethod_getRunLimit();
102         testMethod_getRunStart();
103         testMethod_reorderVisually1();
104         testMethod_reorderVisually2();
105         testMethod_requiresBidi();
106     }
107 
108     private void testMethods4Constructor1() {
109         System.out.println("*** Test methods for constructor 1");
110 
111         String paragraph;
112         Bidi bidi;
113         NumericShaper ns = NumericShaper.getShaper(NumericShaper.ARABIC);
114 
115         for (int textNo = 0; textNo < data4Constructor1.length; textNo++) {
116             paragraph = data4Constructor1[textNo][0];
117             int start = paragraph.indexOf('<')+1;
118             int limit = paragraph.indexOf('>');
119             int testNo;
120 
121             System.out.println("*** Test textNo=" + textNo +
122                 ": Bidi(AttributedCharacterIterator\"" +
123                 toReadableString(paragraph) + "\") " +
124                 "  start=" + start + ", limit=" + limit);
125 
126             // Test 0
127             testNo = 0;
128             System.out.println(" Test#" + testNo +": RUN_DIRECTION_LTR");
129             AttributedString astr = new AttributedString(paragraph);
130             astr.addAttribute(TextAttribute.RUN_DIRECTION,
131                               TextAttribute.RUN_DIRECTION_LTR);
132             bidi = new Bidi(astr.getIterator());
133 
134             callTestEachMethod4Constructor1(textNo, testNo, bidi);
135 
136             // Test 1
137             ++testNo;
138             System.out.println(" Test#" + testNo +
139                 ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(1)");
140             astr = new AttributedString(paragraph);
141             astr.addAttribute(TextAttribute.RUN_DIRECTION,
142                               TextAttribute.RUN_DIRECTION_LTR);
143             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1),
144                               start, limit);
145             bidi = new Bidi(astr.getIterator());
146             callTestEachMethod4Constructor1(textNo, testNo, bidi);
147 
148             // Test 2
149             ++testNo;
150             System.out.println(" Test#" + testNo +
151                 ": RUN_DIERCTION_LTR, BIDI_EMBEDDING(2)");
152             astr = new AttributedString(paragraph);
153             astr.addAttribute(TextAttribute.RUN_DIRECTION,
154                               TextAttribute.RUN_DIRECTION_LTR);
155             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2),
156                               start, limit);
157             bidi = new Bidi(astr.getIterator());
158             callTestEachMethod4Constructor1(textNo, testNo, bidi);
159 
160             // Test 3
161             ++testNo;
162             System.out.println(" Test#" + testNo +
163                 ": RUN_DIRECTIOIN_LTR, BIDI_EMBEDDING(-3)");
164             astr = new AttributedString(paragraph);
165             astr.addAttribute(TextAttribute.RUN_DIRECTION,
166                               TextAttribute.RUN_DIRECTION_LTR);
167             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3),
168                               start, limit);
169             bidi = new Bidi(astr.getIterator());
170             callTestEachMethod4Constructor1(textNo, testNo, bidi);
171 
172             // Test 4
173             ++testNo;
174             System.out.println(" Test#" + testNo +
175                 ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(-4)");
176             astr = new AttributedString(paragraph);
177             astr.addAttribute(TextAttribute.RUN_DIRECTION,
178                               TextAttribute.RUN_DIRECTION_LTR);
179             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4),
180                               start, limit);
181             bidi = new Bidi(astr.getIterator());
182             callTestEachMethod4Constructor1(textNo, testNo, bidi);
183 
184             // Test 5
185             ++testNo;
186             System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL");
187             astr = new AttributedString(paragraph);
188             astr.addAttribute(TextAttribute.RUN_DIRECTION,
189                               TextAttribute.RUN_DIRECTION_RTL);
190             bidi = new Bidi(astr.getIterator());
191             callTestEachMethod4Constructor1(textNo, testNo, bidi);
192 
193             // Test 6
194             ++testNo;
195             System.out.println(" Test#" + testNo +
196                 ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(1)");
197             astr = new AttributedString(paragraph);
198             astr.addAttribute(TextAttribute.RUN_DIRECTION,
199                               TextAttribute.RUN_DIRECTION_RTL);
200             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1),
201                               start, limit);
202             try {
203                 bidi = new Bidi(astr.getIterator());
204                 callTestEachMethod4Constructor1(textNo, testNo, bidi);
205             }
206             catch (IllegalArgumentException e) {
207                 errorHandling("  Unexpected exception: " + e);
208             }
209 
210             // Test 7
211             ++testNo;
212             System.out.println(" Test#" + testNo +
213                 ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(2)");
214             astr = new AttributedString(paragraph);
215             astr.addAttribute(TextAttribute.RUN_DIRECTION,
216                               TextAttribute.RUN_DIRECTION_RTL);
217             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2),
218                               start, limit);
219             try {
220                 bidi = new Bidi(astr.getIterator());
221                 callTestEachMethod4Constructor1(textNo, testNo, bidi);
222             }
223             catch (IllegalArgumentException e) {
224                 errorHandling("  Unexpected exception: " + e);
225             }
226 
227             // Test 8
228             ++testNo;
229             System.out.println(" Test#" + testNo +
230                 ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-3)");
231             astr = new AttributedString(paragraph);
232             astr.addAttribute(TextAttribute.RUN_DIRECTION,
233                               TextAttribute.RUN_DIRECTION_RTL);
234             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3),
235                               start, limit);
236             try {
237                 bidi = new Bidi(astr.getIterator());
238                 callTestEachMethod4Constructor1(textNo, testNo, bidi);
239             }
240             catch (IllegalArgumentException e) {
241                 errorHandling("  Unexpected exception: " + e);
242             }
243 
244             // Test 9
245             ++testNo;
246             System.out.println(" Test#" + testNo +
247                 ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-4)");
248             astr = new AttributedString(paragraph);
249             astr.addAttribute(TextAttribute.RUN_DIRECTION,
250                               TextAttribute.RUN_DIRECTION_RTL);
251             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4),
252                               start, limit);
253             try {
254                 bidi = new Bidi(astr.getIterator());
255                 callTestEachMethod4Constructor1(textNo, testNo, bidi);
256             }
257             catch (IllegalArgumentException e) {
258                 errorHandling("  Unexpected exception: " + e);
259             }
260 
261             // Test 10
262             ++testNo;
263             System.out.println(" Test#" + testNo +
264                 ": TextAttribute not specified");
265             astr = new AttributedString(paragraph);
266             bidi = new Bidi(astr.getIterator());
267             callTestEachMethod4Constructor1(textNo, testNo, bidi);
268 
269             // Test 11
270             ++testNo;
271             System.out.println(" Test#" + testNo +
272                 ": RUN_DIRECTION_LTR, NUMERIC_SHAPING(ARABIC)");
273             astr = new AttributedString(paragraph);
274             astr.addAttribute(TextAttribute.RUN_DIRECTION,
275                               TextAttribute.RUN_DIRECTION_LTR);
276             astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns);
277             bidi = new Bidi(astr.getIterator());
278             callTestEachMethod4Constructor1(textNo, testNo, bidi);
279 
280             // Test 12
281             ++testNo;
282             System.out.println(" Test#" + testNo +
283                  ": RUN_DIRECTION_RTL, NUMERIC_SHAPING(ARABIC)");
284             astr = new AttributedString(paragraph);
285             astr.addAttribute(TextAttribute.RUN_DIRECTION,
286                               TextAttribute.RUN_DIRECTION_RTL);
287             astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns);
288             bidi = new Bidi(astr.getIterator());
289             callTestEachMethod4Constructor1(textNo, testNo, bidi);
290         }
291     }
292 
293     private void testMethods4Constructor2() {
294         System.out.println("*** Test methods for constructor 2");
295 
296         String paragraph;
297         Bidi bidi;
298 
299         for (int textNo = 0; textNo < data4Constructor2.length; textNo++) {
300             paragraph = data4Constructor2[textNo][0];
301             for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) {
302                 int flag = FLAGS[flagNo];
303 
304                 System.out.println("*** Test textNo=" + textNo +
305                     ": Bidi(\"" + toReadableString(paragraph) +
306                     "\", " + getFlagName(flag) + ")");
307 
308                 bidi = new Bidi(paragraph, flag);
309                 callTestEachMethod4Constructor2(textNo, flagNo, bidi);
310             }
311         }
312     }
313 
314     private void testMethods4Constructor3() {
315         System.out.println("*** Test methods for constructor 3");
316 
317         String paragraph;
318         Bidi bidi;
319 
320         for (int textNo = 0; textNo < data4Constructor3.length; textNo++) {
321             paragraph = data4Constructor3[textNo][0];
322             char[] c = paragraph.toCharArray();
323             int start = paragraph.indexOf('<')+1;
324             byte[][] embeddings = (c.length < emb4Constructor3[1][0].length) ?
325                                   emb4Constructor3[0] : emb4Constructor3[1];
326             for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) {
327                 int flag = FLAGS[flagNo];
328                 for (int embNo = 0; embNo < embeddings.length; embNo++) {
329                     int dataNo = flagNo * FLAGS.length + embNo;
330 
331                     System.out.println("*** Test textNo=" + textNo +
332                         ": Bidi(char[]\"" + toReadableString(paragraph) +
333                         "\", 0, embeddings={" + toString(embeddings[embNo]) +
334                         "}, " + c.length + ", " +
335                        getFlagName(flag) + ")" + "  dataNo=" + dataNo);
336 
337                     try {
338                         bidi = new Bidi(c, 0, embeddings[embNo], 0,
339                                         c.length, flag);
340                         callTestEachMethod4Constructor3(textNo, dataNo, bidi);
341                     }
342                     catch (Exception e) {
343                         errorHandling("  Unexpected exception: " + e);
344                     }
345                 }
346             }
347         }
348     }
349 
350     private void testConstructor1() {
351         Bidi bidi;
352 
353         try {
354             bidi = new Bidi(null);
355             errorHandling("Bidi((AttributedCharacterIterator)null) " +
356                 "should throw an IAE.");
357         }
358         catch (IllegalArgumentException e) {
359         }
360         catch (NullPointerException e) {
361             errorHandling("Bidi((AttributedCharacterIterator)null) " +
362                 "should not throw an NPE but an IAE.");
363         }
364 
365         String paragraph = data4Constructor1[1][0];
366         int start = paragraph.indexOf('<')+1;
367         int limit = paragraph.indexOf('>');
368         AttributedString astr = new AttributedString(paragraph);
369         astr.addAttribute(TextAttribute.RUN_DIRECTION,
370                           TextAttribute.RUN_DIRECTION_RTL);
371         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-61),
372                           start, limit);
373         try {
374             bidi = new Bidi(astr.getIterator());
375             for (int i = start; i < limit; i++) {
376                 if (bidi.getLevelAt(i) != 61) {
377                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
378                         i + ") should not be " + bidi.getLevelAt(i) +
379                         " but 60 when BIDI_EMBEDDING is -61.");
380                 }
381             }
382         }
383         catch (Exception e) {
384             errorHandling("  Unexpected exception: " + e);
385         }
386 
387         astr = new AttributedString(paragraph);
388         astr.addAttribute(TextAttribute.RUN_DIRECTION,
389                           TextAttribute.RUN_DIRECTION_RTL);
390         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-62),
391                           start, limit);
392         try {
393             bidi = new Bidi(astr.getIterator());
394             for (int i = start; i < limit; i++) {
395                 if (bidi.getLevelAt(i) != 1) {
396                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " +
397                         "should be 1 when BIDI_EMBEDDING is -62.");
398                 }
399             }
400         }
401         catch (Exception e) {
402             errorHandling("  Unexpected exception: " + e);
403         }
404 
405         astr = new AttributedString(paragraph);
406         astr.addAttribute(TextAttribute.RUN_DIRECTION,
407                           TextAttribute.RUN_DIRECTION_RTL);
408         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(60),
409                           start, limit);
410         try {
411             bidi = new Bidi(astr.getIterator());
412             for (int i = start; i < limit; i++) {
413                 if (bidi.getLevelAt(i) != 61) {
414                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " +
415                         "should be 61 when BIDI_EMBEDDING is 60.");
416                 }
417             }
418         }
419         catch (Exception e) {
420             errorHandling("  Unexpected exception: " + e);
421         }
422 
423         astr = new AttributedString(paragraph);
424         astr.addAttribute(TextAttribute.RUN_DIRECTION,
425                           TextAttribute.RUN_DIRECTION_RTL);
426         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(61),
427                           start, limit);
428         try {
429             bidi = new Bidi(astr.getIterator());
430             for (int i = start; i < limit; i++) {
431                 if (bidi.getLevelAt(i) != 61) {
432                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
433                         i + ") should not be " + bidi.getLevelAt(i) +
434                         " but 61 when BIDI_EMBEDDING is 61.");
435                 }
436             }
437         }
438         catch (Exception e) {
439             errorHandling("  Unexpected exception: " + e);
440         }
441 
442         astr = new AttributedString(paragraph);
443         astr.addAttribute(TextAttribute.RUN_DIRECTION,
444                           TextAttribute.RUN_DIRECTION_RTL);
445         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(62),
446                           start, limit);
447         try {
448             bidi = new Bidi(astr.getIterator());
449             for (int i = start; i < limit; i++) {
450                 if (bidi.getLevelAt(i) != 1) {
451                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt()" +
452                         " should not be " + bidi.getLevelAt(i) +
453                         " but 1 when BIDI_EMBEDDING is 62.");
454                 }
455             }
456         }
457         catch (Exception e) {
458             errorHandling("  Unexpected exception: " + e);
459         }
460     }
461 
462     private void testConstructor2() {
463         Bidi bidi;
464 
465         try {
466             bidi = new Bidi(null, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
467             errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT)" +
468                 " should throw an IAE.");
469         }
470         catch (IllegalArgumentException e) {
471         }
472         catch (NullPointerException e) {
473             errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT) " +
474                 "should not throw an NPE but an IAE.");
475         }
476 
477         try {
478             bidi = new Bidi("abc", -3);
479         }
480         catch (Exception e) {
481             errorHandling("Bidi(\"abc\", -3) should not throw an exception: " +
482                 e);
483         }
484 
485         try {
486             bidi = new Bidi("abc", 2);
487         }
488         catch (Exception e) {
489             errorHandling("Bidi(\"abc\", 2) should not throw an exception: " +
490                 e);
491         }
492     }
493 
494     private void testConstructor3() {
495         char[] text = {'a', 'b', 'c', 'd', 'e'};
496         byte[] embeddings = {0, 0, 0, 0, 0};
497         Bidi bidi;
498 
499         try {
500             bidi = new Bidi(null, 0, embeddings, 0, 5,
501                             Bidi.DIRECTION_LEFT_TO_RIGHT);
502             errorHandling("Bidi(char[], ...) should throw an IAE " +
503                 "when text=null.");
504         }
505         catch (IllegalArgumentException e) {
506         }
507         catch (NullPointerException e) {
508             errorHandling("Bidi(char[], ...) should not throw an NPE " +
509                 "but an IAE when text=null.");
510         }
511 
512         try {
513             bidi = new Bidi(text, -1, embeddings, 0, 5,
514                             Bidi.DIRECTION_LEFT_TO_RIGHT);
515             errorHandling("Bidi(char[], ...) should throw an IAE " +
516                 "when textStart is incorrect(-1: too small).");
517         }
518         catch (IllegalArgumentException e) {
519         }
520         catch (ArrayIndexOutOfBoundsException e) {
521             errorHandling("Bidi(char[], ...) should not throw an NPE " +
522                 "but an IAE when textStart is incorrect(-1: too small).");
523         }
524 
525         try {
526             bidi = new Bidi(text, 4, embeddings, 0, 2,
527                             Bidi.DIRECTION_LEFT_TO_RIGHT);
528             errorHandling("Bidi(char[], ...) should throw an IAE " +
529                 "when textStart is incorrect(4: too large).");
530         }
531         catch (IllegalArgumentException e) {
532         }
533         catch (ArrayIndexOutOfBoundsException e) {
534             errorHandling("Bidi(char[], ...) should not throw an NPE " +
535                 "but an IAE when textStart is incorrect(4: too large).");
536         }
537 
538         byte[] actualLevels = new byte[text.length];
539         byte[] validEmbeddings1 = {0, -61, -60, -2, -1};
540         byte[] expectedLevels1  = {0,  61,  60,  2,  1};
541         try {
542             bidi = new Bidi(text, 0, validEmbeddings1, 0, 5,
543                             Bidi.DIRECTION_LEFT_TO_RIGHT);
544             for (int i = 0; i < text.length; i++) {
545                 actualLevels[i] = (byte)bidi.getLevelAt(i);
546             }
547             if (!Arrays.equals(expectedLevels1, actualLevels)) {
548                 errorHandling("Bidi(char[], ...).getLevelAt()" +
549                     " should be {" + toString(actualLevels) +
550                     "} when embeddings are {" +
551                     toString(expectedLevels1) + "}.");
552             }
553         }
554         catch (Exception e) {
555             errorHandling("Bidi(char[], ...) should not throw an exception " +
556                 "when embeddings is valid(-61).");
557         }
558 
559         byte[] validEmbeddings2 = {0,  61,  60,  2,  1};
560         byte[] expectedLevels2  = {0,  62,  60,  2,  2};
561         try {
562             bidi = new Bidi(text, 0, validEmbeddings2, 0, 5,
563                             Bidi.DIRECTION_LEFT_TO_RIGHT);
564             for (int i = 0; i < text.length; i++) {
565                 actualLevels[i] = (byte)bidi.getLevelAt(i);
566             }
567             if (!Arrays.equals(expectedLevels2, actualLevels)) {
568                 errorHandling("Bidi(char[], ...).getLevelAt()" +
569                     " should be {" + toString(actualLevels) +
570                     "} when embeddings are {" +
571                     toString(expectedLevels2) + "}.");
572             }
573         }
574         catch (Exception e) {
575             errorHandling("Bidi(char[], ...) should not throw an exception " +
576                 "when embeddings is valid(61).");
577         }
578 
579         byte[] invalidEmbeddings1 = {0, -62, 0, 0, 0};
580         try {
581             bidi = new Bidi(text, 0, invalidEmbeddings1, 0, 5,
582                             Bidi.DIRECTION_LEFT_TO_RIGHT);
583             if (bidi.getLevelAt(1) != 0) {
584                 errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " +
585                     "when embeddings[1] is -62.");
586             }
587         }
588         catch (Exception e) {
589             errorHandling("Bidi(char[], ...) should not throw an exception " +
590                 "even when embeddings includes -62.");
591         }
592 
593         byte[] invalidEmbeddings2 = {0, 62, 0, 0, 0};
594         try {
595             bidi = new Bidi(text, 0, invalidEmbeddings2, 0, 5,
596                             Bidi.DIRECTION_LEFT_TO_RIGHT);
597             if (bidi.getLevelAt(1) != 0) {
598                 errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " +
599                     "when embeddings[1] is 62.");
600             }
601         }
602         catch (Exception e) {
603             errorHandling("Bidi(char[], ...) should not throw an exception " +
604                 "even when embeddings includes 62.");
605         }
606 
607         try {
608             bidi = new Bidi(text, 0, embeddings, 0, -1,
609                             Bidi.DIRECTION_LEFT_TO_RIGHT);
610             errorHandling("Bidi(char[], ...) should throw an IAE " +
611                 "when paragraphLength=-1(too small).");
612         }
613         catch (IllegalArgumentException e) {
614         }
615         catch (NegativeArraySizeException e) {
616             errorHandling("Bidi(char[], ...) should not throw an NASE " +
617                 "but an IAE when paragraphLength=-1(too small).");
618         }
619 
620         try {
621             bidi = new Bidi(text, 0, embeddings, 0, 6,
622                             Bidi.DIRECTION_LEFT_TO_RIGHT);
623             errorHandling("Bidi(char[], ...) should throw an IAE " +
624                 "when paragraphLength=6(too large).");
625         }
626         catch (IllegalArgumentException e) {
627         }
628         catch (ArrayIndexOutOfBoundsException e) {
629             errorHandling("Bidi(char[], ...) should not throw an AIOoBE " +
630                 "but an IAE when paragraphLength=6(too large).");
631         }
632 
633         try {
634             bidi = new Bidi(text, 0, embeddings, 0, 4, -3);
635         }
636         catch (Exception e) {
637             errorHandling("Bidi(char[], ...) should not throw an exception " +
638                 "even when flag=-3(too small).");
639         }
640 
641         try {
642             bidi = new Bidi(text, 0, embeddings, 0, 5, 2);
643         }
644         catch (Exception e) {
645             errorHandling("Bidi(char[], ...) should not throw an exception " +
646                 "even when flag=2(too large).");
647         }
648     }
649 
650     private void callTestEachMethod4Constructor1(int textNo,
651                                                  int testNo,
652                                                  Bidi bidi) {
653         testEachMethod(bidi,
654                        data4Constructor1[textNo][0],
655                        data4Constructor1[textNo][testNo+1],
656                        baseIsLTR4Constructor1[textNo][testNo],
657                        isLTR_isRTL4Constructor1[textNo][0][testNo],
658                        isLTR_isRTL4Constructor1[textNo][1][testNo]);
659 System.out.println(bidi.toString());
660     }
661 
662     private void callTestEachMethod4Constructor2(int textNo,
663                                                  int flagNo,
664                                                  Bidi bidi) {
665         testEachMethod(bidi,
666                        data4Constructor2[textNo][0],
667                        data4Constructor2[textNo][flagNo+1],
668                        baseIsLTR4Constructor2[textNo][flagNo],
669                        isLTR_isRTL4Constructor2[textNo][0][flagNo],
670                        isLTR_isRTL4Constructor2[textNo][1][flagNo]);
671 System.out.println(bidi.toString());
672     }
673 
674     private void callTestEachMethod4Constructor3(int textNo,
675                                                  int dataNo,
676                                                  Bidi bidi) {
677         testEachMethod(bidi,
678                        data4Constructor3[textNo][0],
679                        data4Constructor3[textNo][dataNo+1],
680                        baseIsLTR4Constructor3[textNo][dataNo],
681                        isLTR_isRTL4Constructor3[textNo][0][dataNo],
682                        isLTR_isRTL4Constructor3[textNo][1][dataNo]);
683 System.out.println(bidi.toString());
684     }
685 
686     private StringBuilder sb = new StringBuilder();
687     private void testEachMethod(Bidi bidi,
688                                 String text,
689                                 String expectedLevels,
690                                 boolean expectedBaseIsLTR,
691                                 boolean expectedIsLTR,
692                                 boolean expectedIsRTL
693                                ) {
694         /* Test baseIsLeftToRight() */
695         boolean actualBoolean = bidi.baseIsLeftToRight();
696         checkResult("baseIsLeftToRight()", expectedBaseIsLTR, actualBoolean);
697 
698         /* Test getBaseLevel() */
699         int expectedInt = (expectedBaseIsLTR) ? 0 : 1;
700         int actualInt = bidi.getBaseLevel();
701         checkResult("getBaseLevel()", expectedInt, actualInt);
702 
703         /* Test getLength() */
704         expectedInt = text.length();
705         actualInt = bidi.getLength();
706         checkResult("getLength()", expectedInt, actualInt);
707 
708         /* Test getLevelAt() */
709         sb.setLength(0);
710         for (int i = 0; i < text.length(); i++) {
711             sb.append(bidi.getLevelAt(i));
712         }
713         checkResult("getLevelAt()", expectedLevels, sb.toString());
714 
715         /* Test getRunCount() */
716         expectedInt = getRunCount(expectedLevels);
717         actualInt = bidi.getRunCount();
718         checkResult("getRunCount()", expectedInt, actualInt);
719 
720         /* Test getRunLevel(), getRunLimit() and getRunStart() */
721         if (expectedInt == actualInt) {
722             int runCount = expectedInt;
723             int[] expectedRunLevels = getRunLevels_int(runCount, expectedLevels);
724             int[] expectedRunLimits = getRunLimits(runCount, expectedLevels);
725             int[] expectedRunStarts = getRunStarts(runCount, expectedLevels);
726             int[] actualRunLevels = new int[runCount];
727             int[] actualRunLimits = new int[runCount];
728             int[] actualRunStarts = new int[runCount];
729 
730             for (int k = 0; k < runCount; k++) {
731                 actualRunLevels[k] = bidi.getRunLevel(k);
732                 actualRunLimits[k] = bidi.getRunLimit(k);
733                 actualRunStarts[k] = bidi.getRunStart(k);
734             }
735 
736             checkResult("getRunLevel()", expectedRunLevels, actualRunLevels);
737             checkResult("getRunStart()", expectedRunStarts, actualRunStarts);
738             checkResult("getRunLimit()", expectedRunLimits, actualRunLimits);
739         }
740 
741         /* Test isLeftToRight() */
742         boolean expectedBoolean = expectedIsLTR;
743         actualBoolean = bidi.isLeftToRight();
744         checkResult("isLeftToRight()", expectedBoolean, actualBoolean);
745 
746         /* Test isMixed() */
747         expectedBoolean = !(expectedIsLTR || expectedIsRTL);
748         actualBoolean = bidi.isMixed();
749         checkResult("isMixed()", expectedBoolean, actualBoolean);
750 
751         /* Test isRightToLeft() */
752         expectedBoolean = expectedIsRTL;
753         actualBoolean = bidi.isRightToLeft();
754         checkResult("isRightToLeft()", expectedBoolean, actualBoolean);
755     }
756 
757     private int getRunCount(String levels) {
758         int len = levels.length();
759         char c = levels.charAt(0);
760         int runCount = 1;
761 
762         for (int index = 1; index < len; index++) {
763             if (levels.charAt(index) != c) {
764                 runCount++;
765                 c = levels.charAt(index);
766             }
767         }
768 
769         return runCount;
770     }
771 
772     private int[] getRunLevels_int(int runCount, String levels) {
773         int[] array = new int[runCount];
774         int len = levels.length();
775         char c = levels.charAt(0);
776         int i = 0;
777         array[i++] = c - '0';
778 
779         for (int index = 1; index < len; index++) {
780             if (levels.charAt(index) != c) {
781                 c = levels.charAt(index);
782                 array[i++] = c - '0';
783             }
784         }
785 
786         return array;
787     }
788 
789     private byte[] getRunLevels_byte(int runCount, String levels) {
790         byte[] array = new byte[runCount];
791         int len = levels.length();
792         char c = levels.charAt(0);
793         int i = 0;
794         array[i++] = (byte)(c - '0');
795 
796         for (int index = 1; index < len; index++) {
797             if (levels.charAt(index) != c) {
798                 c = levels.charAt(index);
799                 array[i++] = (byte)(c - '0');
800             }
801         }
802 
803         return array;
804     }
805 
806     private int[] getRunLimits(int runCount, String levels) {
807         int[] array = new int[runCount];
808         int len = levels.length();
809         char c = levels.charAt(0);
810         int i = 0;
811 
812         for (int index = 1; index < len; index++) {
813             if (levels.charAt(index) != c) {
814                 c = levels.charAt(index);
815                 array[i++] = index;
816             }
817         }
818         array[i] = len;
819 
820         return array;
821     }
822 
823     private int[] getRunStarts(int runCount, String levels) {
824         int[] array = new int[runCount];
825         int len = levels.length();
826         char c = levels.charAt(0);
827         int i = 1;
828 
829         for (int index = 1; index < len; index++) {
830             if (levels.charAt(index) != c) {
831                 c = levels.charAt(index);
832                 array[i++] = index;
833             }
834         }
835 
836         return array;
837     }
838 
839     private String[] getObjects(int runCount, String text, String levels) {
840         String[] array = new String[runCount];
841         int[] runLimits = getRunLimits(runCount, levels);
842         int runStart = 0;
843 
844         for (int i = 0; i < runCount; i++) {
845             array[i] = text.substring(runStart, runLimits[i]);
846             runStart = runLimits[i];
847         }
848 
849         return array;
850     }
851 
852     private void testMethod_createLineBidi1() {
853         System.out.println("*** Test createLineBidi() 1");
854 
855         String str = " ABC 123. " + HebrewABC + " " + NKo123 + ". ABC 123";
856 
857         int lineStart = str.indexOf('.') + 2;
858         int lineLimit = str.lastIndexOf('.') + 2;
859         Bidi bidi = new Bidi(str, FLAGS[0]);
860         Bidi lineBidi = bidi.createLineBidi(lineStart, lineLimit);
861 
862         checkResult("getBaseLevel()",
863             bidi.getBaseLevel(), lineBidi.getBaseLevel());
864         checkResult("getLevelAt(5)",
865             bidi.getLevelAt(lineStart+5), lineBidi.getLevelAt(5));
866     }
867 
868     private void testMethod_createLineBidi2() {
869         System.out.println("*** Test createLineBidi() 2");
870 
871         Bidi bidi = new Bidi(data4Constructor1[0][0], FLAGS[0]);
872         int len = data4Constructor1[0][0].length();
873 
874         try {
875             Bidi lineBidi = bidi.createLineBidi(0, len);
876         }
877         catch (Exception e) {
878             errorHandling("createLineBidi(0, textLength)" +
879                 " should not throw an exception.");
880         }
881 
882         try {
883             Bidi lineBidi = bidi.createLineBidi(-1, len);
884             errorHandling("createLineBidi(-1, textLength)" +
885                 " should throw an IAE.");
886         }
887         catch (IllegalArgumentException e) {
888         }
889 
890         try {
891             Bidi lineBidi = bidi.createLineBidi(0, len+1);
892             errorHandling("createLineBidi(0, textLength+1)" +
893                 " should throw an IAE.");
894         }
895         catch (IllegalArgumentException e) {
896         }
897     }
898 
899     /*
900      * Confirm that getLevelAt() doesn't throw an exception for invalid offset
901      * unlike ICU4J.
902      */
903     private void testMethod_getLevelAt() {
904         System.out.println("*** Test getLevelAt()");
905 
906         Bidi bidi = new Bidi(data4Constructor1[1][0], FLAGS[0]);
907         int len = data4Constructor1[1][0].length();
908 
909         try {
910             int level = bidi.getLevelAt(-1);
911             if (level != bidi.getBaseLevel()) {
912                 errorHandling("getLevelAt(-1) returned a wrong level." +
913                     " Expected=" + bidi.getBaseLevel() + ", got=" + level);
914             }
915         }
916         catch (Exception e) {
917             errorHandling("getLevelAt(-1) should not throw an exception.");
918         }
919 
920         try {
921             int level = bidi.getLevelAt(len+1);
922             if (level != bidi.getBaseLevel()) {
923                 errorHandling("getLevelAt(textLength+1)" +
924                     " returned a wrong level." +
925                     " Expected=" + bidi.getBaseLevel() + ", got=" + level);
926             }
927         }
928         catch (Exception e) {
929             errorHandling("getLevelAt(-1) should not throw an exception.");
930         }
931     }
932 
933     private void testMethod_getRunLevel() {
934         System.out.println("*** Test getRunLevel()");
935 
936         String str = "ABC 123";
937         int length = str.length();
938         Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
939 
940         try {
941             if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2
942                 bidi.getRunLevel(0) != 0 ||   // runCount - 1
943                 bidi.getRunLevel(1) != 0 ||   // runCount
944                 bidi.getRunLevel(2) != 0) {   // runCount + 1
945                 errorHandling("getRunLevel() should return 0" +
946                     " when getRunCount() is 1.");
947             }
948         }
949         catch (Exception e) {
950             errorHandling("getRunLevel() should not throw an exception " +
951                 "when getRunCount() is 1.");
952         }
953 
954         str = "ABC " + HebrewABC + " 123";
955         length = str.length();
956         bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
957 
958         try {
959             bidi.getRunLevel(-1);
960             errorHandling("getRunLevel() should throw an AIOoBE " +
961                 "when run is -1(too small).");
962         }
963         catch (ArrayIndexOutOfBoundsException e) {
964         }
965         catch (IllegalArgumentException e) {
966             errorHandling("getRunLevel() should not throw an IAE " +
967                 "but an AIOoBE when run is -1(too small).");
968         }
969 
970         try {
971             bidi.getRunLevel(0);
972             bidi.getRunLevel(1);
973             bidi.getRunLevel(2);
974         }
975         catch (Exception e) {
976             errorHandling("getRunLevel() should not throw an exception" +
977                 " when run is from 0 to 2(runCount-1).");
978         }
979 
980         try {
981             bidi.getRunLevel(3);
982             errorHandling("getRunLevel() should throw an AIOoBE" +
983                 " when run is 3(same as runCount).");
984         }
985         catch (ArrayIndexOutOfBoundsException e) {
986         }
987         catch (IllegalArgumentException e) {
988             errorHandling("getRunLevel() should not throw an IAE " +
989                 "but an AIOoBE when run is 3(same as runCount).");
990         }
991     }
992 
993     private void testMethod_getRunLimit() {
994         System.out.println("*** Test getRunLimit()");
995 
996         String str = "ABC 123";
997         int length = str.length();
998         Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
999 
1000         try {
1001             if (bidi.getRunLimit(-1) != length ||  // runCount - 2
1002                 bidi.getRunLimit(0) != length ||   // runCount - 1
1003                 bidi.getRunLimit(1) != length ||   // runCount
1004                 bidi.getRunLimit(2) != length) {   // runCount + 1
1005                 errorHandling("getRunLimit() should return " + length +
1006                     " when getRunCount() is 1.");
1007             }
1008         }
1009         catch (Exception e) {
1010             errorHandling("getRunLimit() should not throw an exception " +
1011                 "when getRunCount() is 1.");
1012         }
1013 
1014         str = "ABC " + ArabicABC + " 123";
1015         length = str.length();
1016         bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
1017 
1018         try {
1019             bidi.getRunLimit(-1);
1020             errorHandling("getRunLimit() should throw an AIOoBE " +
1021                 "when run is -1(too small).");
1022         }
1023         catch (ArrayIndexOutOfBoundsException e) {
1024         }
1025         catch (IllegalArgumentException e) {
1026             errorHandling("getRunLimit() should not throw an IAE " +
1027                 "but an AIOoBE when run is -1(too small).");
1028         }
1029 
1030         try {
1031             bidi.getRunLimit(0);
1032             bidi.getRunLimit(1);
1033             bidi.getRunLimit(2);
1034         }
1035         catch (ArrayIndexOutOfBoundsException e) {
1036             errorHandling("getRunLimit() should not throw an AIOOBE " +
1037                 "when run is from 0 to 2(runCount-1).");
1038         }
1039 
1040         try {
1041             bidi.getRunLimit(3);
1042             errorHandling("getRunLimit() should throw an AIOoBE " +
1043                 "when run is 3(same as runCount).");
1044         }
1045         catch (ArrayIndexOutOfBoundsException e) {
1046         }
1047         catch (IllegalArgumentException e) {
1048             errorHandling("getRunLimit() should not throw an IAE " +
1049                 "but an AIOoBE when run is 3(same as runCount).");
1050         }
1051     }
1052 
1053     private void testMethod_getRunStart() {
1054         System.out.println("*** Test getRunStart()");
1055 
1056         String str = "ABC 123";
1057         int length = str.length();
1058         Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
1059 
1060         try {
1061             if (bidi.getRunStart(-1) != 0 ||  // runCount - 2
1062                 bidi.getRunStart(0) != 0 ||   // runCount - 1
1063                 bidi.getRunStart(1) != 0 ||   // runCount
1064                 bidi.getRunStart(2) != 0) {   // runCount + 1
1065                 errorHandling("getRunStart() should return 0" +
1066                     " when getRunCount() is 1.");
1067             }
1068         }
1069         catch (Exception e) {
1070             errorHandling("getRunLimit() should not throw an exception" +
1071                 " when getRunCount() is 1.");
1072         }
1073 
1074         str = "ABC " + NKoABC + " 123";
1075         length = str.length();
1076         bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
1077 
1078         try {
1079             bidi.getRunStart(-1);
1080             errorHandling("getRunStart() should throw an AIOoBE" +
1081                 " when run is -1(too small).");
1082         }
1083         catch (ArrayIndexOutOfBoundsException e) {
1084         }
1085         catch (IllegalArgumentException e) {
1086             errorHandling("getRunStart() should not throw an IAE " +
1087                 "but an AIOoBE when run is -1(too small).");
1088         }
1089 
1090         try {
1091             bidi.getRunStart(0);
1092             bidi.getRunStart(1);
1093             bidi.getRunStart(2);
1094         }
1095         catch (ArrayIndexOutOfBoundsException e) {
1096             errorHandling("getRunStart() should not throw an AIOOBE " +
1097                 "when run is from 0 to 2(runCount-1).");
1098         }
1099 
1100         try {
1101             if (bidi.getRunStart(3) != length) {
1102                 errorHandling("getRunStart() should return " + length +
1103                     " when run is 3(same as runCount).");
1104             }
1105         }
1106         catch (Exception e) {
1107             errorHandling("getRunStart() should not throw an exception " +
1108                 "when run is 3(same as runCount).");
1109         }
1110 
1111         try {
1112             bidi.getRunStart(4);
1113             errorHandling("getRunStart() should throw an AIOoBE " +
1114                 "when run is runCount+1(too large).");
1115         }
1116         catch (ArrayIndexOutOfBoundsException e) {
1117         }
1118         catch (IllegalArgumentException e) {
1119             errorHandling("getRunStart() should not throw an IAE " +
1120                 "but an AIOoBE when run is runCount+1(too large).");
1121         }
1122     }
1123 
1124     private void testMethod_reorderVisually1() {
1125         System.out.println("*** Test reorderVisually() 1");
1126 
1127         for (int textNo = 0; textNo < data4reorderVisually.length; textNo++) {
1128             Object[] objects = data4reorderVisually[textNo][0];
1129             byte[] levels = getLevels(data4reorderVisually[textNo]);
1130             Object[] expectedObjects = data4reorderVisually[textNo][2];
1131 
1132             Bidi.reorderVisually(levels, 0, objects, 0, objects.length);
1133 
1134             checkResult("textNo=" + textNo + ": reorderVisually(levels=[" +
1135                 toString(levels) + "], objects=[" + toString(objects) + "])",
1136                 expectedObjects, objects);
1137         }
1138     }
1139 
1140     private void testMethod_reorderVisually2() {
1141         System.out.println("*** Test reorderVisually() 2");
1142 
1143         Object[] objects = data4reorderVisually[0][0];
1144         byte[] levels = getLevels(data4reorderVisually[0]);
1145         int count = objects.length;
1146         int llen = levels.length;
1147         int olen = objects.length;
1148 
1149         try {
1150             Bidi.reorderVisually(null, 0, objects, 0, count);
1151             errorHandling("reorderVisually() should throw a NPE " +
1152                 "when levels is null.");
1153         }
1154         catch (NullPointerException e) {
1155         }
1156 
1157         try {
1158             Bidi.reorderVisually(levels, -1, objects, 0, count);
1159             errorHandling("reorderVisually() should throw an IAE " +
1160                 "when levelStart is -1.");
1161         }
1162         catch (IllegalArgumentException e) {
1163         }
1164         catch (ArrayIndexOutOfBoundsException e) {
1165             errorHandling("reorderVisually() should not throw an AIOoBE " +
1166                 "but an IAE when levelStart is -1.");
1167         }
1168 
1169         try {
1170             Bidi.reorderVisually(levels, llen, objects, 0, count);
1171             errorHandling("reorderVisually() should throw an IAE " +
1172                 "when levelStart is 6(levels.length).");
1173         }
1174         catch (IllegalArgumentException e) {
1175         }
1176         catch (ArrayIndexOutOfBoundsException e) {
1177             errorHandling("reorderVisually() should not throw an AIOoBE " +
1178                 "but an IAE when levelStart is 6(levels.length).");
1179         }
1180 
1181         try {
1182             Bidi.reorderVisually(levels, 0, null, 0, count);
1183             errorHandling("reorderVisually() should throw a NPE" +
1184                 " when objects is null.");
1185         }
1186         catch (NullPointerException e) {
1187         }
1188 
1189         try {
1190             Bidi.reorderVisually(levels, 0, objects, -1, count);
1191             errorHandling("reorderVisually() should throw an IAE" +
1192                 " when objectStart is -1.");
1193         }
1194         catch (IllegalArgumentException e) {
1195         }
1196         catch (ArrayIndexOutOfBoundsException e) {
1197             errorHandling("reorderVisually() should not throw an AIOoBE " +
1198                 "but an IAE when objectStart is -1.");
1199         }
1200 
1201         try {
1202             Bidi.reorderVisually(levels, 0, objects, 6, objects.length);
1203             errorHandling("reorderVisually() should throw an IAE " +
1204                 "when objectStart is 6(objects.length).");
1205         }
1206         catch (IllegalArgumentException e) {
1207         }
1208 
1209         try {
1210             Bidi.reorderVisually(levels, 0, objects, 0, -1);
1211             errorHandling("reorderVisually() should throw an IAE " +
1212                 "when count is -1.");
1213         }
1214         catch (IllegalArgumentException e) {
1215         }
1216         catch (NegativeArraySizeException e) {
1217             errorHandling("reorderVisually() should not throw an NASE " +
1218                 "but an IAE when count is -1.");
1219         }
1220 
1221         try {
1222             Bidi.reorderVisually(levels, 0, objects, 0, count+1);
1223             errorHandling("reorderVisually() should throw an IAE " +
1224                 "when count is 7(objects.length+1).");
1225         }
1226         catch (IllegalArgumentException e) {
1227         }
1228         catch (ArrayIndexOutOfBoundsException e) {
1229             errorHandling("reorderVisually() should not throw an AIOoBE " +
1230                 "but an IAE when count is 7(objects.length+1).");
1231         }
1232 
1233         try {
1234             Bidi.reorderVisually(levels, 0, objects, 0, 0);
1235             checkResult("reorderVisually(count=0)",
1236                 data4reorderVisually[0][0], objects);
1237         }
1238         catch (Exception e) {
1239             errorHandling("reorderVisually() should not throw an exception" +
1240                 " when count is 0.");
1241         }
1242     }
1243 
1244     private void testMethod_requiresBidi() {
1245         System.out.println("*** Test requiresBidi()");
1246 
1247         String paragraph;
1248         char[] text;
1249         Bidi bidi;
1250 
1251         for (int textNo = 0; textNo < data4Constructor2.length; textNo++) {
1252             paragraph = data4Constructor2[textNo][0];
1253             text = paragraph.toCharArray();
1254             boolean rBidi = Bidi.requiresBidi(text, 0, text.length);
1255             if (rBidi != requiresBidi4Constructor2[textNo]) {
1256                 error = true;
1257                 System.err.println("Unexpected requiresBidi() value" +
1258                     " for requiresBidi(\"" + paragraph + "\", " + 0 + ", " +
1259                     text.length + ")." +
1260                     "\n    Expected: " + requiresBidi4Constructor2[textNo] +
1261                     "\n    Got     : " + rBidi);
1262             } else if (verbose) {
1263                 System.out.println("  Okay : requiresBidi() for" +
1264                     " requiresBidi(\"" + paragraph + "\", " + 0 + ", " +
1265                     text.length + ")  Got: " + rBidi);
1266             }
1267         }
1268 
1269         char[] txt = {'A', 'B', 'C', 'D', 'E'};
1270         int textLength = txt.length;
1271 
1272         try {
1273             Bidi.requiresBidi(txt, -1, textLength);
1274             errorHandling("requiresBidi() should throw an IAE" +
1275                 " when start is -1(too small).");
1276         }
1277         catch (IllegalArgumentException e) {
1278         }
1279         catch (ArrayIndexOutOfBoundsException e) {
1280             errorHandling("requiresBidi() should not throw an AIOoBE " +
1281                 "but an IAE when start is -1(too small).");
1282         }
1283 
1284         try {
1285             Bidi.requiresBidi(txt, textLength, textLength);
1286         }
1287         catch (Exception e) {
1288             errorHandling("requiresBidi() should not throw an exception " +
1289                 "when start is textLength.");
1290         }
1291 
1292         try {
1293             Bidi.requiresBidi(txt, textLength+1, textLength);
1294             errorHandling("requiresBidi() should throw an IAE" +
1295                 " when start is textLength+1(too large).");
1296         }
1297         catch (IllegalArgumentException e) {
1298         }
1299 
1300         try {
1301             Bidi.requiresBidi(txt, 0, -1);
1302             errorHandling("requiresBidi() should throw an IAE" +
1303                 " when limit is -1(too small).");
1304         }
1305         catch (IllegalArgumentException e) {
1306         }
1307 
1308         try {
1309             Bidi.requiresBidi(txt, 0, textLength+1);
1310             errorHandling("requiresBidi() should throw an IAE" +
1311                 " when limit is textLength+1(too large).");
1312         }
1313         catch (IllegalArgumentException e) {
1314         }
1315         catch (ArrayIndexOutOfBoundsException e) {
1316             errorHandling("requiresBidi() should not throw an AIOoBE " +
1317                 "but an IAE when limit is textLength+1(too large).");
1318         }
1319     }
1320 
1321     private void checkResult(String name,
1322                              int expectedValue,
1323                              int actualValue) {
1324         if (expectedValue != actualValue) {
1325             errorHandling("Unexpected " + name + " value." +
1326                 " Expected: " + expectedValue + " Got: " + actualValue);
1327         } else if (verbose) {
1328             System.out.println("  Okay : " + name + " = " + actualValue);
1329         }
1330     }
1331 
1332     private void checkResult(String name,
1333                              boolean expectedValue,
1334                              boolean actualValue) {
1335         if (expectedValue != actualValue) {
1336             errorHandling("Unexpected " + name + " value." +
1337                 " Expected: " + expectedValue + " Got: " + actualValue);
1338         } else if (verbose) {
1339             System.out.println("  Okay : " + name + " = " + actualValue);
1340         }
1341     }
1342 
1343     private void checkResult(String name,
1344                              String expectedValue,
1345                              String actualValue) {
1346         if (!expectedValue.equals(actualValue)) {
1347             errorHandling("Unexpected " + name + " value." +
1348                 "\n\tExpected: \"" + expectedValue + "\"" +
1349                 "\n\tGot:      \"" + actualValue + "\"");
1350         } else if (verbose) {
1351             System.out.println("  Okay : " + name + " = \"" +
1352                 actualValue + "\"");
1353         }
1354     }
1355 
1356     private void checkResult(String name,
1357                              int[] expectedValues,
1358                              int[] actualValues) {
1359         if (!Arrays.equals(expectedValues, actualValues)) {
1360             errorHandling("Unexpected " + name + " value." +
1361                 "\n\tExpected: " + toString(expectedValues) + "" +
1362                 "\n\tGot:      " + toString(actualValues) + "");
1363         } else if (verbose) {
1364             System.out.println("  Okay : " + name + " = " +
1365                 toString(actualValues));
1366         }
1367     }
1368 
1369     private void checkResult(String name,
1370                              Object[] expectedValues,
1371                              Object[] actualValues) {
1372         if (!Arrays.equals(expectedValues, actualValues)) {
1373             errorHandling("Unexpected " + name + " value." +
1374                 "\n\tExpected: [" + toString(expectedValues) +
1375                 "]\n\tGot:      [" + toString(actualValues) + "]");
1376         } else if (verbose) {
1377             System.out.println("  Okay : " + name + " Reordered objects = [" +
1378                 toString(actualValues) + "]");
1379         }
1380     }
1381 
1382     private void errorHandling(String msg) {
1383         if (abort) {
1384             throw new RuntimeException("Error: " + msg);
1385         } else {
1386             error = true;
1387             System.err.println("**Error:" + msg);
1388         }
1389     }
1390 
1391     private String toString(int[] values) {
1392         StringBuilder sb = new StringBuilder();
1393         for (int i = 0; i < values.length-1; i++) {
1394             sb.append((int)values[i]);
1395             sb.append(' ');
1396         }
1397         sb.append((int)values[values.length-1]);
1398 
1399         return sb.toString();
1400     }
1401 
1402     private String toString(byte[] values) {
1403         StringBuilder sb = new StringBuilder();
1404         for (int i = 0; i < values.length-1; i++) {
1405             sb.append((byte)values[i]);
1406             sb.append(' ');
1407         }
1408         sb.append((byte)values[values.length-1]);
1409 
1410         return sb.toString();
1411     }
1412 
1413     private String toString(Object[] values) {
1414         StringBuilder sb = new StringBuilder();
1415         String name;
1416 
1417         for (int i = 0; i < values.length-1; i++) {
1418             if ((name = getStringName((String)values[i])) != null) {
1419                 sb.append(name);
1420                 sb.append(", ");
1421             } else {
1422                 sb.append('"');
1423                 sb.append((String)values[i]);
1424                 sb.append("\", ");
1425             }
1426         }
1427         if ((name = getStringName((String)values[values.length-1])) != null) {
1428             sb.append(name);
1429         } else {
1430             sb.append('"');
1431             sb.append((String)values[values.length-1]);
1432             sb.append('\"');
1433         }
1434 
1435         return sb.toString();
1436     }
1437 
1438     private String getStringName(String str) {
1439         if (ArabicABC.equals(str)) return "ArabicABC";
1440         else if (Arabic123.equals(str)) return "Arabic123";
1441         else if (PArabicABC.equals(str)) return "ArabicABC(Presentation form)";
1442         else if (HebrewABC.equals(str)) return "HebrewABC";
1443         else if (KharoshthiABC.equals(str)) return "KharoshthiABC(RTL)";
1444         else if (Kharoshthi123.equals(str)) return "Kharoshthi123(RTL)";
1445         else if (NKoABC.equals(str)) return "NKoABC(RTL)";
1446         else if (NKo123.equals(str)) return "NKo123(RTL)";
1447         else if (OsmanyaABC.equals(str)) return "OsmanyaABC(LTR)";
1448         else if (Osmanya123.equals(str)) return "Osmanya123(LTR)";
1449         else return null;
1450     }
1451 
1452     private String getFlagName(int flag) {
1453         if (flag == -2 || flag == 0x7e) return FLAGNAMES[0];
1454         else if (flag == -1 || flag == 0x7f) return FLAGNAMES[1];
1455         else if (flag == 0) return FLAGNAMES[2];
1456         else if (flag == 1) return FLAGNAMES[3];
1457         else return "Unknown(0x" + Integer.toHexString(flag) + ")";
1458     }
1459 
1460     private String toReadableString(String str) {
1461          String s = str;
1462 
1463          s = s.replaceAll(ArabicABC, "ArabicABC");
1464          s = s.replaceAll(Arabic123, "Arabic123");
1465          s = s.replaceAll(PArabicABC, "ArabicABC(Presentation form)");
1466          s = s.replaceAll(HebrewABC, "HebrewABC");
1467          s = s.replaceAll(KharoshthiABC, "KharoshthiABC");
1468          s = s.replaceAll(Kharoshthi123, "Kharoshthi123");
1469          s = s.replaceAll(NKoABC, "NKoABC");
1470          s = s.replaceAll(NKo123, "NKo123");
1471          s = s.replaceAll(OsmanyaABC, "OsmanyaABC");
1472          s = s.replaceAll(Osmanya123, "Osmanya123");
1473 
1474          return s;
1475     }
1476 
1477     private  byte[] getLevels(Object[][] data) {
1478         int levelLength = data[0].length;
1479         byte[] array = new byte[levelLength];
1480         int textIndex = 0;
1481 
1482         for (int i = 0; i < levelLength; i++) {
1483             array[i] = (byte)(((String)data[1][0]).charAt(textIndex) - '0');
1484             textIndex += ((String)data[0][i]).length();
1485         }
1486 
1487         return array;
1488     }
1489 
1490 
1491     /* Bidi pubilc constants */
1492     private static final int[] FLAGS = {
1493         Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT,  // -2 (0x7e in ICU4J)
1494         Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT,  // -1 (0x7f in ICU4J)
1495         Bidi.DIRECTION_LEFT_TO_RIGHT,          //  0
1496         Bidi.DIRECTION_RIGHT_TO_LEFT           //  1
1497     };
1498 
1499     /* Bidi pubilc constants names */
1500     private static final String[] FLAGNAMES = {
1501         "DIRECTION_DEFAULT_LEFT_TO_RIGHT",  // -2
1502         "DIRECTION_DEFAULT_RIGHT_TO_LEFT",  // -1
1503         "DIRECTION_LEFT_TO_RIGHT",          //  0
1504         "DIRECTION_RIGHT_TO_LEFT",          //  1
1505     };
1506 
1507     /* Bidirectional Character Types */
1508     private static final char L   = '\u200E';
1509     private static final char R   = '\u202F';
1510     private static final char LRE = '\u202A';
1511     private static final char RLE = '\u202B';
1512     private static final char PDF = '\u202C';
1513     private static final char LRO = '\u202D';
1514     private static final char RLO = '\u202E';
1515 
1516     /*
1517      *  0x05D0-0x05EA:   [R]   Hewbrew letters (Strong)
1518      *  0x0627-0x063A:   [AL]  Arabic letters (Strong)
1519      *  0x0660-0x0669:   [AN]  Arabic-Indic digits (Weak)
1520      *  0x07CA-0x07E7:   [R]   NKo letters (Strong)
1521      *  0x07C0-0x07C9:   [R]   NKo digits (Strong)
1522      *  0xFE50-0xFEFF:   [AL]  Arabic presentaion form (Strong)
1523      *  0x10480-0x1049D: [L]   Osmanya letters (Strong)
1524      *  0x104A0-0x104A9: [L]   Osmanya digits (Strong)
1525      *  0x10A10-0x10A33: [R]   Kharoshthi letters (Strong)
1526      *  0x10A40-0x10A43: [R]   Kharoshthi digits (Strong)
1527      *
1528      *  0x200E:          [L]   Left-to-right mark (Implicit, Strong)
1529      *  0x200F:          [R]   Right-to-left mark (Implicit, Strong)
1530      *  0x202A:          [LRE] Left-to-right embedding (Explicit, Strong)
1531      *  0x202B:          [RLE] Right-to-left embedding (Explicit, Strong)
1532      *  0x202C:          [PDF] Pop directional formatting (Explicit, Weak)
1533      *  0x202D:          [LRO] Left-to-right override (Explicit, Strong)
1534      *  0x202E:          [RLO] Right-to-left override (Explicit, Strong)
1535      */
1536 
1537     /* Right-to-left */
1538     private static String ArabicABC = "\u0627\u0628\u0629";
1539     private static String Arabic123 = "\u0661\u0662\u0663";
1540     private static String PArabicABC = "\uFE97\uFE92\uFE8E";
1541     private static String HebrewABC = "\u05D0\u05D1\u05D2";
1542     private static String KharoshthiABC =
1543         new String(Character.toChars(0x10A10)) +
1544         new String(Character.toChars(0x10A11)) +
1545         new String(Character.toChars(0x10A12));
1546     private static String Kharoshthi123 =
1547         new String(Character.toChars(0x10A40)) +
1548         new String(Character.toChars(0x10A41)) +
1549         new String(Character.toChars(0x10A42));
1550     private static String NKoABC = "\u07CA\u07CB\u07CC";
1551     private static String NKo123 = "\u07C1\u07C2\u07C3";
1552 
1553     /* Left-to-right */
1554     private static String OsmanyaABC =
1555         new String(Character.toChars(0x10480)) +
1556         new String(Character.toChars(0x10481)) +
1557         new String(Character.toChars(0x10482));
1558     private static String Osmanya123 =
1559         new String(Character.toChars(0x104A0)) +
1560         new String(Character.toChars(0x104A1)) +
1561         new String(Character.toChars(0x104A2));
1562 
1563     /* --------------------------------------------------------------------- */
1564 
1565     /*
1566      * Test data for Bidi(char[], ...) constructor and methods
1567      */
1568 
1569     /* Text for Bidi processing and its levels */
1570     private static String[][] data4Constructor1 = {
1571         /* For Text #0 */
1572         {"abc <ABC XYZ> xyz.",
1573              "000000000000000000", "000002222222000000", "000000000000000000",
1574              "000003333333000000", "000000000000000000",
1575              "222222222222222221", "222222222222222221", "222222222222222221",
1576              "222113333333112221", "222224444444222221",
1577              "000000000000000000", "000000000000000000", "222222222222222221"},
1578 
1579         /* For Text #1 */
1580         {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.",
1581              "000001111111000000", "000001111111000000", "000003333333000000",
1582              "000003333333000000", "000000000000000000",
1583              "222111111111112221", "222111111111112221", "222223333333222221",
1584              "222113333333112221", "222224444444222221",
1585              "000001111111000000", "000001111111000000", "222111111111112221"},
1586 
1587         /* For Text #2 */
1588         {NKoABC + " <ABC XYZ> " + NKo123 + ".",
1589              "111000000000001110", "111112222222111110", "111002222222001110",
1590              "111113333333111110", "111004444444001110",
1591              "111112222222111111", "111112222222111111", "111112222222111111",
1592              "111111111111111111", "111114444444111111",
1593              "111112222222111111", "111000000000001110", "111112222222111111"},
1594 
1595         /* For Text #3 */
1596         {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".",
1597              "111111111222111110", "111111111222111110", "111003333444001110",
1598              "111113333333111110", "111004444444001110",
1599              "111111111222111111", "111111111222111111", "111113333444111111",
1600              "111111111111111111", "111114444444111111",
1601              "111111111222111111", "111111111222111110", "111111111222111111"},
1602 
1603         /* For Text #4 */
1604         {"abc <" + NKoABC + " 123> xyz.",
1605              "000001111222000000", "000001111222000000", "000003333444000000",
1606              "000003333333000000", "000000000000000000",
1607              "222111111222112221", "222111111222112221", "222223333444222221",
1608              "222113333333112221", "222224444444222221",
1609              "000001111222000000", "000001111222000000", "222111111222112221"},
1610 
1611         /* For Text #5 */
1612         {"abc <ABC " + NKo123 + "> xyz.",
1613              "000000000111000000", "000002221111000000", "000002222333000000",
1614              "000003333333000000", "000000000000000000",
1615              "222222221111112221", "222222221111112221", "222222222333222221",
1616              "222113333333112221", "222224444444222221",
1617              "000000000111000000", "000000000111000000", "222222221111112221"},
1618 
1619         /* For Text #6 */
1620         {ArabicABC + " <" + NKoABC + " 123" + "> " + Arabic123 + ".",
1621              "111111111222112220", "111111111222112220", "111003333444002220",
1622              "111113333333112220", "111004444444002220",
1623              "111111111222112221", "111111111222112221", "111113333444112221",
1624              "111113333333112221", "111114444444112221",
1625              "111111111222112221", "111111111222112220", "111111111222112221"},
1626 
1627         /* For Text #7 */
1628         {ArabicABC + " <XYZ " + NKoABC + "> " + Arabic123 + ".",
1629              "111000000111112220", "111112221111112220", "111002222333002220",
1630              "111113333333112220", "111004444444002220",
1631              "111112221111112221", "111112221111112221", "111112222333112221",
1632              "111113333333112221", "111114444444112221",
1633              "111112221111112221", "111000000111112220", "111112221111112221"},
1634 
1635         /* For Text #8 */
1636         {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " +
1637          Osmanya123 + ".",
1638              "000000001111111111111000000000", "000000001111111111111000000000",
1639              "000000003333333333333000000000", "000000003333333333333000000000",
1640              "000000000000000000000000000000",
1641              "222222111111111111111112222221", "222222111111111111111112222221",
1642              "222222223333333333333222222221", "222222113333333333333112222221",
1643              "222222224444444444444222222221",
1644              "000000001111111111111000000000", "000000001111111111111000000000",
1645              "222222111111111111111112222221"},
1646 
1647         /* For Text #9 */
1648         {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " +
1649          Kharoshthi123 + ".",
1650              "111111000000000000000001111110", "111111112222222222222111111110",
1651              "111111002222222222222001111110", "111111113333333333333111111110",
1652              "111111004444444444444001111110",
1653              "111111112222222222222111111111", "111111112222222222222111111111",
1654              "111111112222222222222111111111", "111111111111111111111111111111",
1655              "111111114444444444444111111111",
1656              "111111112222222222222111111111", "111111000000000000000001111110",
1657              "111111112222222222222111111111"},
1658     };
1659 
1660     /* Golden data for baseIsLeftToRight() results */
1661     private static boolean[][] baseIsLTR4Constructor1 = {
1662         /* For Text #0 */
1663         {true,  true,  true,  true,  true,
1664          false, false, false, false, false,
1665          true,  true,  false},
1666 
1667         /* For Text #1 */
1668         {true,  true,  true,  true,  true,
1669          false, false, false, false, false,
1670          true,  true,  false},
1671 
1672         /* For Text #2 */
1673         {true,  true,  true,  true,  true,
1674          false, false, false, false, false,
1675          false, true,  false},
1676 
1677         /* For Text #3 */
1678         {true,  true,  true,  true,  true,
1679          false, false, false, false, false,
1680          false, true,  false},
1681 
1682         /* For Text #4 */
1683         {true,  true,  true,  true,  true,
1684          false, false, false, false, false,
1685          true,  true,  false},
1686 
1687         /* For Text #5 */
1688         {true,  true,  true,  true,  true,
1689          false, false, false, false, false,
1690          true,  true,  false},
1691 
1692         /* For Text #6 */
1693         {true,  true,  true,  true,  true,
1694          false, false, false, false, false,
1695          false, true,  false},
1696 
1697         /* For Text #7 */
1698         {true,  true,  true,  true,  true,
1699          false, false, false, false, false,
1700          false, true,  false},
1701 
1702         /* For Text #8 */
1703         {true,  true,  true,  true,  true,
1704          false, false, false, false, false,
1705          true,  true,  false},
1706 
1707         /* For Text #9 */
1708         {true,  true,  true,  true,  true,
1709          false, false, false, false, false,
1710          false, true,  false},
1711     };
1712 
1713     /* Golden data for isLeftToRight() & isRightToLeft() results */
1714     private static boolean[][][] isLTR_isRTL4Constructor1 = {
1715         /* For Text #0 */
1716          /* isLeftToRight() results */
1717         {{true,  false, true,  false, true,
1718           false, false, false, false, false,
1719           true,  true,  false},
1720          /* isRightToLeft() results   */
1721          {false, false, false, false, false,
1722           false, false, false, false, false,
1723           false, false, false}},
1724 
1725         /* For Text #1 */
1726          /* isLeftToRight() results */
1727         {{false, false, false, false, true,
1728           false, false, false, false, false,
1729           false, false, false},
1730          /* isRightToLeft() results   */
1731          {false, false, false, false, false,
1732           false, false, false, false, false,
1733           false, false, false}},
1734 
1735         /* For Text #2 */
1736          /* isLeftToRight() results */
1737         {{false, false, false, false, false,
1738           false, false, false, false, false,
1739           false, false, false},
1740          /* isRightToLeft() results   */
1741          {false, false, false, false, false,
1742           false, false, false, true,  false,
1743           false, false, false}},
1744 
1745         /* For Text #3 */
1746          /* isLeftToRight() results */
1747         {{false, false, false, false, false,
1748           false, false, false, false, false,
1749           false, false, false},
1750          /* isRightToLeft() results   */
1751          {false, false, false, false, false,
1752           false, false, false, true,  false,
1753           false, false, false}},
1754 
1755         /* For Text #4 */
1756          /* isLeftToRight() results */
1757         {{false, false, false, false, true,
1758           false, false, false, false, false,
1759           false, false, false},
1760          /* isRightToLeft() results   */
1761          {false, false, false, false, false,
1762           false, false, false, false, false,
1763           false, false, false}},
1764 
1765         /* For Text #5 */
1766          /* isLeftToRight() results */
1767         {{false, false, false, false, true,
1768           false, false, false, false, false,
1769           false, false, false},
1770          /* isRightToLeft() results   */
1771          {false, false, false, false, false,
1772           false, false, false, false, false,
1773           false, false, false}},
1774 
1775         /* For Text #6 */
1776          /* isLeftToRight() results */
1777         {{false, false, false, false, false,
1778           false, false, false, false, false,
1779           false, false, false},
1780          /* isRightToLeft() results   */
1781          {false, false, false, false, false,
1782           false, false, false, false, false,
1783           false, false, false}},
1784 
1785         /* For Text #7 */
1786          /* isLeftToRight() results */
1787         {{false, false, false, false, false,
1788           false, false, false, false, false,
1789           false, false, false},
1790          /* isRightToLeft() results   */
1791          {false, false, false, false, false,
1792           false, false, false, false, false,
1793           false, false, false}},
1794 
1795         /* For Text #8 */
1796          /* isLeftToRight() results */
1797         {{false, false, false, false, true,
1798           false, false, false, false, false,
1799           false, false, false},
1800          /* isRightToLeft() results   */
1801          {false, false, false, false, false,
1802           false, false, false, false, false,
1803           false, false, false}},
1804 
1805         /* For Text #9 */
1806          /* isLeftToRight() results */
1807         {{false, false, false, false, false,
1808           false, false, false, false, false,
1809           false, false, false},
1810          /* isRightToLeft() results   */
1811          {false, false, false, false, false,
1812           false, false, false, true,  false,
1813           false, false, false}},
1814     };
1815 
1816     /* --------------------------------------------------------------------- */
1817 
1818     /*
1819      * Test data for Bidi(String, int) constructor and methods
1820      */
1821 
1822     /* Text for Bidi processing and its levels */
1823     private static String[][] data4Constructor2 = {
1824         /* For Text #0 */
1825         {" ABC 123.",
1826              "000000000", "000000000", "000000000", "122222221"},
1827 
1828         /* For Text #1 */
1829         {" ABC " + HebrewABC + " " + NKo123 + " 123.",
1830              "00000111111112220", "00000111111112220", "00000111111112220",
1831              "12221111111112221"},
1832 
1833         /* For Text #2 */
1834         {" ABC " + ArabicABC + " " + Arabic123 + " 123.",
1835              "00000111122212220", "00000111122212220", "00000111122212220",
1836              "12221111122212221"},
1837 
1838         /* For Text #3 */
1839         {" " + NKoABC + " ABC 123 " + NKo123 + ".",
1840              "11111222222211111", "11111222222211111", "01110000000001110",
1841              "11111222222211111"},
1842 
1843         /* For Text #4 */
1844         {" " + ArabicABC + " ABC 123 " + Arabic123 + ".",
1845              "11111222222212221", "11111222222212221", "01110000000002220",
1846              "11111222222212221"},
1847 
1848         /* For Text #5 */
1849         {" " + HebrewABC + " " + NKo123 + ".",
1850              "111111111", "111111111", "011111110", "111111111"},
1851 
1852         /* For Text #6 */
1853         {" " + ArabicABC + " " + Arabic123 + ".",
1854              "111112221", "111112221", "011112220", "111112221"},
1855 
1856         /* For Text #7 */
1857         {" " + KharoshthiABC + " " + Kharoshthi123 + ".",
1858              "111111111111111", "111111111111111", "011111111111110",
1859              "111111111111111"},
1860 
1861         /* For Text #8 */
1862         {L + HebrewABC + " " + NKo123 + ".",
1863              "011111110", "011111110", "011111110", "211111111"},
1864 
1865         /* For Text #9 */
1866         {R + "ABC " + Osmanya123 + ".",
1867              "000000000000", "000000000000", "000000000000", "122222222221"},
1868 
1869         /* For Text #10 */
1870         {"ABC " + PArabicABC + " " + PArabicABC + " 123",
1871              "000011111111222", "000011111111222", "000011111111222",
1872              "222111111111222"},
1873 
1874         /* For Text #11 */
1875         {RLE + "ABC " + HebrewABC + " " + NKo123 + "." + PDF,
1876              "22221111111110", "22221111111110", "22221111111110",
1877              "44443333333331"},
1878 
1879         /* For Text #12 */
1880         {"He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + ".\"",
1881              "000000000222211111111000", "000000000222211111111000",
1882              "000000000222211111111000", "222222211444433333333111"},
1883 
1884         /* For Text #13 */
1885         {LRO + "He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF +
1886          ".\"" + PDF,
1887              "22222222224444333333332220", "22222222224444333333332220",
1888              "22222222224444333333332220", "22222222224444333333332221"},
1889 
1890         /* For Text #14 */
1891         {LRO + "He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF +
1892          ".\"",  // PDF missing
1893              "2222222222444433333333222", "2222222222444433333333222",
1894              "2222222222444433333333222", "2222222222444433333333222"},
1895 
1896         /* For Text #15 */
1897         {"Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC +
1898          " " + NKo123 + PDF + "\"" + PDF + "'?",
1899              "0000000000000222222222244443333333322000",
1900              "0000000000000222222222244443333333322000",
1901              "0000000000000222222222244443333333322000",
1902              "2222222222222222222222244443333333322111"},
1903 
1904         /* For Text #16 */
1905         {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " +
1906          HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?" + PDF,
1907              "111111111111112222222222444433333333221110",
1908              "111111111111112222222222444433333333221110",
1909              "111111111111112222222222444433333333221110",
1910              "333333333333334444444444666655555555443331"},
1911 
1912         /* For Text #17 */
1913         {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " +
1914          HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?",  // PDF missing
1915              "11111111111111222222222244443333333322111",
1916              "11111111111111222222222244443333333322111",
1917              "11111111111111222222222244443333333322111",
1918              "33333333333333444444444466665555555544333"},
1919 
1920         /* For Text #18 */
1921         {" ABC (" + ArabicABC + " " + Arabic123 + ") 123.",
1922              "0000001111222112220", "0000001111222112220",
1923              "0000001111222112220", "1222111111222112221"},
1924 
1925         /* For Text #19 */
1926         {" " + HebrewABC + " (ABC 123) " + NKo123 + ".",
1927              "1111112222222111111", "1111112222222111111",
1928              "0111000000000001110", "1111112222222111111"},
1929 
1930         /* For Text #20 */
1931         {" He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF + ".\" ",
1932              "00000000002222111111110000", "00000000002222111111110000",
1933              "00000000002222111111110000", "12222222114444333333331111"},
1934 
1935         /* For Text #21 */
1936         {" Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC +
1937          " " + NKo123 + PDF + "\"" + PDF + "'? ",
1938              "000000000000002222222222444433333333220000",
1939              "000000000000002222222222444433333333220000",
1940              "000000000000002222222222444433333333220000",
1941              "122222222222222222222222444433333333221111"},
1942 
1943         /* For Text #22 */
1944         {RLE + OsmanyaABC + " " + KharoshthiABC + " " + Kharoshthi123 + "." +
1945          PDF,
1946              "22222221111111111111110", "22222221111111111111110",
1947              "22222221111111111111110", "44444443333333333333331"},
1948     };
1949 
1950     /* Golden data for baseIsLeftToRight() results */
1951     private static boolean[][] baseIsLTR4Constructor2 = {
1952         /* For Text #0 - $4  */
1953         {true,  true,  true,  false},
1954         {true,  true,  true,  false},
1955         {true,  true,  true,  false},
1956         {false, false, true,  false},
1957         {false, false, true,  false},
1958 
1959         /* For Text #5 - $9  */
1960         {false, false, true,  false},
1961         {false, false, true,  false},
1962         {false, false, true,  false},
1963         {true,  true,  true,  false},
1964         {true,  true,  true,  false},
1965 
1966         /* For Text #10 - $14  */
1967         {true,  true,  true,  false},
1968         {true,  true,  true,  false},
1969         {true,  true,  true,  false},
1970         {true,  true,  true,  false},
1971         {true,  true,  true,  false},
1972 
1973         /* For Text #15 - $19  */
1974         {true,  true,  true,  false},
1975         {true,  true,  true,  false},
1976         {true,  true,  true,  false},
1977         {true,  true,  true,  false},
1978         {false, false, true,  false},
1979 
1980         /* For Text #20 - $22  */
1981         {true,  true,  true,  false},
1982         {true,  true,  true,  false},
1983         {true,  true,  true,  false},
1984     };
1985 
1986     /* Golden data for isLeftToRight() & isRightToLeft() results */
1987     private static boolean[][][] isLTR_isRTL4Constructor2 = {
1988         /* isLeftToRight() results   &   isRightToLeft() results   */
1989         /* For Text #0 - $4  */
1990         {{true,  true,  true,  false}, {false, false, false, false}},
1991         {{false, false, false, false}, {false, false, false, false}},
1992         {{false, false, false, false}, {false, false, false, false}},
1993         {{false, false, false, false}, {false, false, false, false}},
1994         {{false, false, false, false}, {false, false, false, false}},
1995 
1996         /* For Text #5 - $9  */
1997         {{false, false, false, false}, {true,  true,  false, true }},
1998         {{false, false, false, false}, {false, false, false, false}},
1999         {{false, false, false, false}, {true,  true,  false, true }},
2000         {{false, false, false, false}, {false, false, false, false}},
2001         {{true,  true,  true,  false}, {false, false, false, false}},
2002 
2003         /* For Text #10 - $14  */
2004         {{false, false, false, false}, {false, false, false, false}},
2005         {{false, false, false, false}, {false, false, false, false}},
2006         {{false, false, false, false}, {false, false, false, false}},
2007         {{false, false, false, false}, {false, false, false, false}},
2008         {{false, false, false, false}, {false, false, false, false}},
2009 
2010         /* For Text #15 - $19  */
2011         {{false, false, false, false}, {false, false, false, false}},
2012         {{false, false, false, false}, {false, false, false, false}},
2013         {{false, false, false, false}, {false, false, false, false}},
2014         {{false, false, false, false}, {false, false, false, false}},
2015         {{false, false, false, false}, {false, false, false, false}},
2016 
2017         /* For Text #20 - $22  */
2018         {{false, false, false, false}, {false, false, false, false}},
2019         {{false, false, false, false}, {false, false, false, false}},
2020         {{false, false, false, false}, {false, false, false, false}},
2021     };
2022 
2023     /* Golden data for requiresBidi() results */
2024     private static boolean[] requiresBidi4Constructor2 = {
2025         /* For Text #0 - $9  */
2026         false, true,  true,  true,  true,
2027         true,  true,  true,  true,  false,
2028 
2029         /* For Text #10 - $19  */
2030         true,  true,  true,  true,  true,
2031         true,  true,  true,  true,  true,
2032 
2033         /* For Text #20 - $22  */
2034         true,  true,  true,
2035     };
2036 
2037     /* --------------------------------------------------------------------- */
2038 
2039     /*
2040      * Test data for Bidi(char[], ...) constructor and methods
2041      */
2042 
2043     /* Enbeddings */
2044     private static byte[][][] emb4Constructor3 = {
2045         /* Embeddings for paragraphs which don't include surrogate pairs. */
2046         {{0, 0, 0, 0, 0,  1,  1,  1,  1,  1,  1,  1, 0, 0, 0, 0, 0, 0},
2047          {0, 0, 0, 0, 0,  2,  2,  2,  2,  2,  2,  2, 0, 0, 0, 0, 0, 0},
2048          {0, 0, 0, 0, 0, -3, -3, -3, -3, -3, -3, -3, 0, 0, 0, 0, 0, 0},
2049          {0, 0, 0, 0, 0, -4, -4, -4, -4, -4, -4, -4, 0, 0, 0, 0, 0, 0}},
2050 
2051         /* Embeddings for paragraphs which include surrogate pairs. */
2052         {{ 0,  0,  0,  0,  0,  0,  0,  0,
2053            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
2054            0,  0,  0,  0,  0,  0,  0,  0,  0},
2055          { 0,  0,  0,  0,  0,  0,  0,  0,
2056            2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
2057            0,  0,  0,  0,  0,  0,  0,  0,  0},
2058          { 0,  0,  0,  0,  0,  0,  0,  0,
2059           -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
2060            0,  0,  0,  0,  0,  0,  0,  0,  0},
2061          { 0,  0,  0,  0,  0,  0,  0,  0,
2062           -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
2063            0,  0,  0,  0,  0,  0,  0,  0,  0}},
2064     };
2065 
2066     /* Text for Bidi processing and its levels */
2067     private static String[][] data4Constructor3 = {
2068         /* For Text #0 */
2069         {"abc <ABC XYZ> xyz.",
2070              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2071              "000002222222000000", "000000000000000000",
2072              "000003333333000000", "000000000000000000",
2073              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2074              "222222222222222221", "222222222222222221",
2075              "222113333333112221", "222224444444222221",
2076              /* DIRECTION_LEFT_TO_RIGHT */
2077              "000002222222000000", "000000000000000000",
2078              "000003333333000000", "000000000000000000",
2079              /* DIRECTION_RIGHT_TO_LEFT */
2080              "222222222222222221", "222222222222222221",
2081              "222113333333112221", "222224444444222221"},
2082 
2083         /* For Text #1 */
2084         {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.",
2085              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2086              "000001111111000000", "000003333333000000",
2087              "000003333333000000", "000000000000000000",
2088              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2089              "222111111111112221", "222223333333222221",
2090              "222113333333112221", "222224444444222221",
2091              /* DIRECTION_LEFT_TO_RIGHT */
2092              "000001111111000000", "000003333333000000",
2093              "000003333333000000", "000000000000000000",
2094              /* DIRECTION_RIGHT_TO_LEFT */
2095              "222111111111112221", "222223333333222221",
2096              "222113333333112221", "222224444444222221"},
2097 
2098         /* For Text #2 */
2099         {NKoABC + " <ABC XYZ> " + NKo123 + ".",
2100              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2101              "111112222222111111", "111112222222111111",
2102              "111111111111111111", "111114444444111111",
2103              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2104              "111112222222111111", "111112222222111111",
2105              "111111111111111111", "111114444444111111",
2106              /* DIRECTION_LEFT_TO_RIGHT */
2107              "111112222222111110", "111002222222001110",
2108              "111113333333111110", "111004444444001110",
2109              /* DIRECTION_RIGHT_TO_LEFT */
2110              "111112222222111111", "111112222222111111",
2111              "111111111111111111", "111114444444111111"},
2112 
2113         /* For Text #3 */
2114         {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".",
2115              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2116              "111111111222111111", "111113333444111111",
2117              "111111111111111111", "111114444444111111",
2118              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2119              "111111111222111111", "111113333444111111",
2120              "111111111111111111", "111114444444111111",
2121              /* DIRECTION_LEFT_TO_RIGHT */
2122              "111111111222111110", "111003333444001110",
2123              "111113333333111110", "111004444444001110",
2124              /* DIRECTION_RIGHT_TO_LEFT */
2125              "111111111222111111", "111113333444111111",
2126              "111111111111111111", "111114444444111111"},
2127 
2128         /* For Text #4 */
2129         {"abc <123 456> xyz.",
2130              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2131              "000002221222000000", "000000000000000000",
2132              "000003333333000000", "000000000000000000",
2133              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2134              "222222222222222221", "222222222222222221",
2135              "222113333333112221", "222224444444222221",
2136              /* DIRECTION_LEFT_TO_RIGHT */
2137              "000002221222000000", "000000000000000000",
2138              "000003333333000000", "000000000000000000",
2139              /* DIRECTION_RIGHT_TO_LEFT */
2140              "222222222222222221", "222222222222222221",
2141              "222113333333112221", "222224444444222221"},
2142 
2143         /* For Text #5 */
2144         {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " +
2145          Osmanya123 + ".",
2146              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2147              "000000001111111111111000000000", "000000003333333333333000000000",
2148              "000000003333333333333000000000", "000000000000000000000000000000",
2149              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2150              "222222111111111111111112222221", "222222223333333333333222222221",
2151              "222222113333333333333112222221", "222222224444444444444222222221",
2152              /* DIRECTION_LEFT_TO_RIGHT */
2153              "000000001111111111111000000000", "000000003333333333333000000000",
2154              "000000003333333333333000000000", "000000000000000000000000000000",
2155              /* DIRECTION_RIGHT_TO_LEFT */
2156              "222222111111111111111112222221", "222222223333333333333222222221",
2157              "222222113333333333333112222221", "222222224444444444444222222221"},
2158 
2159         /* For Text #6 */
2160         {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " +
2161          Kharoshthi123 + ".",
2162              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2163              "111111112222222222222111111111", "111111112222222222222111111111",
2164              "111111111111111111111111111111", "111111114444444444444111111111",
2165              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2166              "111111112222222222222111111111", "111111112222222222222111111111",
2167              "111111111111111111111111111111", "111111114444444444444111111111",
2168              /* DIRECTION_LEFT_TO_RIGHT */
2169              "111111112222222222222111111110", "111111002222222222222001111110",
2170              "111111113333333333333111111110", "111111004444444444444001111110",
2171              /* DIRECTION_RIGHT_TO_LEFT */
2172              "111111112222222222222111111111", "111111112222222222222111111111",
2173              "111111111111111111111111111111", "111111114444444444444111111111"},
2174     };
2175 
2176     /* Golden data for baseIsLeftToRight() results */
2177     private static boolean[][] baseIsLTR4Constructor3 = {
2178         /* For Text #0 */
2179         {true,  true,  true,  true,    // DIRECTION_DEFAULT_LEFT_TO_RIGHT
2180          true,  true,  true,  true,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
2181          true,  true,  true,  true,    // DIRECTION_LEFT_TO_RIGHT
2182          false, false, false, false},  // DIRECTION_RIGHT_TO_LEFT
2183 
2184         /* For Text #1 */
2185         {true,  true,  true,  true,
2186          true,  true,  true,  true,
2187          true,  true,  true,  true,
2188          false, false, false, false},
2189 
2190         /* For Text #2 */
2191         {false, false, false, false,
2192          false, false, false, false,
2193          true,  true,  true,  true,
2194          false, false, false, false},
2195 
2196         /* For Text #3 */
2197         {false, false, false, false,
2198          false, false, false, false,
2199          true,  true,  true,  true,
2200          false, false, false, false},
2201 
2202         /* For Text #4 */
2203         {true,  true,  true,  true,
2204          true,  true,  true,  true,
2205          true,  true,  true,  true,
2206          false, false, false, false},
2207 
2208         /* For Text #5 */
2209         {true,  true,  true,  true,
2210          true,  true,  true,  true,
2211          true,  true,  true,  true,
2212          false, false, false, false},
2213 
2214         /* For Text #6 */
2215         {false, false, false, false,
2216          false, false, false, false,
2217          true,  true,  true,  true,
2218          false, false, false, false},
2219     };
2220 
2221     /* Golden data for isLeftToRight() & isRightToLeft() results */
2222     private static boolean[][][] isLTR_isRTL4Constructor3 = {
2223         /* For Text #0 */
2224          /* isLeftToRight() results */
2225         {{false, true,  false, true,     // DIRECTION_DEFAULT_LEFT_TO_RIGHT
2226           false, false, false, false,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
2227           false, true,  false, true,     // DIRECTION_LEFT_TO_RIGHT
2228           false, false, false, false},   // DIRECTION_RIGHT_TO_LEFT
2229          /* isRightToLeft() results   */
2230          {false, false, false, false,    // DIRECTION_DEFAULT_LEFT_TO_RIGHT
2231           false, false, false, false,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
2232           false, false, false, false,    // DIRECTION_LEFT_TO_RIGHT
2233           false, false, false, false}},  // DIRECTION_RIGHT_TO_LEFTT
2234 
2235         /* For Text #1 */
2236          /* isLeftToRight() results */
2237         {{false, false, false, true,
2238           false, false, false, false,
2239           false, false, false, true,
2240           false, false, false, false},
2241          /* isRightToLeft() results   */
2242          {false, false, false, false,
2243           false, false, false, false,
2244           false, false, false, false,
2245           false, false, false, false}},
2246 
2247         /* For Text #2 */
2248          /* isLeftToRight() results */
2249         {{false, false, false, false,
2250           false, false, false, false,
2251           false, false, false, false,
2252           false, false, false, false},
2253          /* isRightToLeft() results   */
2254          {false, false, true,  false,
2255           false, false, true,  false,
2256           false, false, false, false,
2257           false, false, true,  false}},
2258 
2259         /* For Text #3 */
2260          /* isLeftToRight() results */
2261         {{false, false, false, false,
2262           false, false, false, false,
2263           false, false, false, false,
2264           false, false, false, false},
2265          /* isRightToLeft() results   */
2266          {false, false, true,  false,
2267           false, false, true,  false,
2268           false, false, false, false,
2269           false, false, true,  false}},
2270 
2271         /* For Text #4 */
2272          /* isLeftToRight() results */
2273         {{false, true,  false, true,
2274           false, false, false, false,
2275           false, true,  false, true,
2276           false, false, false, false },
2277          /* isRightToLeft() results   */
2278          {false, false, false, false,
2279           false, false, false, false,
2280           false, false, false, false,
2281           false, false, false, false}},
2282 
2283         /* For Text #5 */
2284          /* isLeftToRight() results */
2285         {{false, false, false, true,
2286           false, false, false, false,
2287           false, false, false, true,
2288           false, false, false, false},
2289          /* isRightToLeft() results   */
2290          {false, false, false, false,
2291           false, false, false, false,
2292           false, false, false, false,
2293           false, false, false, false}},
2294 
2295         /* For Text #6 */
2296          /* isLeftToRight() results */
2297         {{false, false, false, false,
2298           false, false, false, false,
2299           false, false, false, false,
2300           false, false, false, false},
2301          /* isRightToLeft() results   */
2302          {false, false, true,  false,
2303           false, false, true,  false,
2304           false, false, false, false,
2305           false, false, true,  false}},
2306     };
2307 
2308     /* --------------------------------------------------------------------- */
2309 
2310     /*
2311      * Test data for reorderVisually() methods
2312      */
2313 
2314     private static Object[][][] data4reorderVisually = {
2315         {{"ABC", " ", "abc", " ", ArabicABC, "."},   // Original text
2316          {"000000001110"},                           // levels
2317          {"ABC", " ", "abc", " ", ArabicABC, "."}},  // Reordered text
2318 
2319         {{"ABC", " ", HebrewABC, " ", NKoABC, "."},
2320          {"222111111111"},
2321          {".", NKoABC, " ", HebrewABC, " ", "ABC"}},
2322 
2323         {{OsmanyaABC, " ", HebrewABC, " ", KharoshthiABC, "."},
2324          {"222222111111111111"},
2325          {".", KharoshthiABC, " ", HebrewABC, " ", OsmanyaABC,}},
2326 
2327         {{"ABC", " ", Osmanya123, " ", "\"", OsmanyaABC, " ", Kharoshthi123,
2328           " ", KharoshthiABC, ".", "\""},
2329          {"0000000000002222221111111111111100"},
2330          {"ABC", " ", Osmanya123, " ", "\"", KharoshthiABC, " ", Kharoshthi123,
2331           " ", OsmanyaABC, ".", "\""}},
2332     };
2333 
2334 }